#pragma once

#include "LeGraphicsView.h"

#include <QGraphicsView>
#include "Palette.h"

namespace LeGraphicsView
{

    class Scene;
    class GridModel;
    class RulerBar;
    class Palette;
    class Settings;
    class GraphicsCrossHair;
    class GraphicsGrid;

    class OLDGRAPHICSVIEW_EXPORT View : public QGraphicsView
    {
        Q_OBJECT

    public:
        // TBD: Rename to cursor mark => origin, relative origin and cursor positions
        enum MouseCursor
        {
            NoMouseCursor = 0,
            SmallMouseCursor,
            LargeMouseCursor
        };
        Q_ENUM(MouseCursor)

        enum OriginMark
        {
            NoOriginMark = 0,
            SmallOriginMark,
            LargeOriginMark
        };
        Q_ENUM(OriginMark)

        explicit View(QWidget *parent = nullptr);
        ~View();

        Scene *scene() const;
        void setScene(Scene *scene);

        void scaleView(qreal scaleFactor);
        void translateView(qreal dx, qreal dy);

        void setPalette(Palette palette);
        Palette palette() const;

        void zoomIn(QPointF pos, qreal factor);

        void setHardwareAccelerationEnabled(bool enabled);
        bool hardwareAccelerationEnabled() const;

        void setRulerEnabled(bool enabled);
        bool rulerEnabled() const;

        void setGridEnabled(bool enabled);
        bool gridEnabled() const;

        void setMinimalGridSize(int pixels);
        int minimalGridSize() const;

        void setGridCoarseMultiplier(int multiplier);
        int gridCoarseMultiplier() const;

        void setGridCoarseLineStyle(Qt::PenStyle style);
        Qt::PenStyle gridCoarseLineStyle() const;

        void setGridFineLineStyle(Qt::PenStyle style);
        Qt::PenStyle gridFineLineStyle() const;

        void setMouseCursor(MouseCursor cursor);
        MouseCursor mouseCursor() const;

        void setOriginMark(OriginMark mark);
        OriginMark originMark() const;

        const GridModel *gridModel() const;

        void setCursorPos(const QPointF &scenePos);
        QPointF cursorPos() const;

        void setOriginPos(const QPointF &scenePos);
        QPointF originPos() const;

        QRectF visibleSceneRect() const;
        void setVisibleSceneRect(const QRectF &rect);

    signals:
        void settingsChanged();

    public slots:
        void applySettings(const Settings &settings);

    protected:
        void updateForeground();
        void updateBackground();

    private:
        bool m_hardwareAccelerationEnabled;
        bool m_rulerEnabled;

        GridModel *m_gridModel;
        QWidget *m_topLeftWidget;
        RulerBar *m_horizontalRuler;
        QWidget *m_topRightWidget;
        RulerBar *m_verticalRuler;
        QWidget *m_bottomLeftWidget;

        bool m_gridEnabled;
        GraphicsGrid *m_grid;

        GraphicsCrossHair *m_originCrossHair;
        GraphicsCrossHair *m_cursorCrossHair;


        Palette m_palette;
        void applyPalette();

        void setupView();
        void setupLayout();
        void applyDefaultSettings();
        void setupGrid();

        // QGraphicsView interface
    protected:
        void drawBackground(QPainter *painter, const QRectF &rect) override;
        void drawForeground(QPainter *painter, const QRectF &rect) override;

        // QAbstractScrollArea interface
    protected:
        void scrollContentsBy(int dx, int dy) override;

        // QWidget interface
    protected:
        void resizeEvent(QResizeEvent *event) override;
        void wheelEvent(QWheelEvent *event) override;

        // QObject interface
    public:
        bool eventFilter(QObject *watched, QEvent *event) override;
    };

}
